package com.aispeech.detector.utils;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaPlayer;
import android.media.audiofx.BassBoost;
import android.media.audiofx.Virtualizer;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

public class SamplePlayer {

    private final String TAG = "SamplePlayer";

    private final int PLAY_SAMPLE_RATE = 16000;

    private MediaPlayer mMediaPlayer;
    private int audioListIndex = 0;
    private ArrayList<String> audioFileList;

    private Virtualizer mVirtualizer;
    private BassBoost mBassBoost;

    private AudioTrack mAudioTrack;

    private boolean mIsPlayLoop = false;
    private SamplePlayerStateListener mListener;

    public SamplePlayer(SamplePlayerStateListener listener) {
        this.mListener = listener;
    }

    public void trackStop() {
        Log.d(TAG, "trackStop: ");
        if ((mAudioTrack != null) && (mAudioTrack.getState() == AudioTrack.STATE_INITIALIZED)) {
            if (mAudioTrack.getPlayState() != AudioTrack.PLAYSTATE_STOPPED) {
                mAudioTrack.flush();
                mAudioTrack.stop();
                mAudioTrack = null;
            }
        }
    }

    public void trackPlay(int sessionId, final String pcmFilePath) {
        Log.d(TAG, "trackPlay() ");
        if (TextUtils.isEmpty(pcmFilePath)) {
            Log.w(TAG, "trackPlay: pcmFilePath is empty");
            return;
        }
        try {
            final int bufferSize = AudioTrack.getMinBufferSize(PLAY_SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat
                    .ENCODING_PCM_16BIT);
            Log.d(TAG, "trackPlay: getMinBufferSize = " + bufferSize);

            if (mAudioTrack == null) {
                if (sessionId == 0) {
                    mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, PLAY_SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO,
                            AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);
                } else {
                    Log.d(TAG, "trackPlay: sessionId = " + sessionId);
                    mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, PLAY_SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize
                            , AudioTrack.MODE_STREAM, sessionId);
                }
            }

            int state = mAudioTrack.getState();
            Log.d(TAG, "trackPlay: state = " + state);
            if (state != AudioTrack.STATE_INITIALIZED) {
                Log.e(TAG, "can not play ,current state is not equals 1");
                return;
            }

            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
//                        InputStream in = VoiceApplication.getAppContext().getResources().openRawResource(R.raw.lmrw_16k_16b_1c);
                        InputStream in = new FileInputStream(new File(pcmFilePath));
                        int length = in.available();
                        Log.d(TAG, "trackPlay: lenght = " + length);
                        if (length < 32 * 1000) {
                            Log.w(TAG, "run: audio file size too small");
                            return;
                        }
                        byte[] buffer = new byte[bufferSize];

                        long skip = in.skip(44);

                        Log.d(TAG, "trackPlay: head = " + skip);
                        int readCount;

                        mListener.onStart();
                        mAudioTrack.play();

                        while ((readCount = in.read(buffer)) != -1) {

//                            Log.d(TAG, "trackPlay: readCount = " + readCount);
                            if (null == mAudioTrack) {
                                Log.w(TAG, "run: audio track is null");
                                break;
                            }
                            int writeResult = mAudioTrack.write(buffer, 0, readCount);
//                            Log.d(TAG, "trackPlay: writeResult = " + writeResult);
                            if (writeResult >= 0) {
                                //success
                            } else {
                                //fail
                                continue;
                            }
                        }
                        Log.d(TAG, "trackPlay: play end");
                        mListener.onStop();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void playStart(String audiofile) {
        Log.d(TAG, "startPlay() called with: audioPatch = [" + audiofile + "]");
        try {
            if (null != mMediaPlayer) {
                mMediaPlayer.reset();
                mMediaPlayer.release();
                mMediaPlayer = null;
            }
            if (!TextUtils.isEmpty(audiofile)) {
                mMediaPlayer = new MediaPlayer();

                if (audiofile.contains(File.separator)) {
                    audioFileList = FileUtils.getAllFile(audiofile, false);
                    if (audioFileList.size() < 1) {
                        Log.e(TAG, "playStart: no audio file in this path;" + audiofile);
                        return;
                    }

                    playAudio(audioFileList.get(0));
                } else {
                    String af = Environment.getExternalStorageDirectory().getPath()
                            + File.separator + audiofile;
                    playAudio(af);
                }

                int playSessionId = mMediaPlayer.getAudioSessionId();
                Log.d(TAG, "playStart: playSessionId = " + playSessionId);
//            setPlayEffect(playSessionId);

                mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mediaPlayer) {
                        Log.d(TAG, "onPrepared: ");
                        // 开始播放
                        mediaPlayer.start();
                    }
                });

                mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer mp) {
                        Log.d(TAG, "onCompletion: ");
                        if (null != audioFileList && audioFileList.size() > 0 && audioListIndex < audioFileList.size() - 1) {
                            playAudio(audioFileList.get(++audioListIndex));
                        } else {
                            if (mIsPlayLoop) {
                                mMediaPlayer.start();
                                mMediaPlayer.setLooping(true);
                            } else {
                                if (null != audioFileList) {
                                    audioFileList.clear();
                                }
                                audioListIndex = 0;

                                mMediaPlayer.stop();
                                mMediaPlayer.release();
                                mMediaPlayer = null;
                            }
                        }
                    }
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
            playStop();
        }

    }

    public void setPlayVirtualizerEffect(int preStrength) {
        Log.d(TAG, "setPlayVirtualizerEffect() called with: preStrenth = [" + preStrength + "]");

        if (mVirtualizer != null) {
            mVirtualizer.setEnabled(false);
            mVirtualizer.release();
            mVirtualizer = null;
        }
        if (mMediaPlayer != null) {
            mVirtualizer = new Virtualizer(0, mMediaPlayer.getAudioSessionId());
            mVirtualizer.setEnabled(true);
            if (mVirtualizer.getStrengthSupported()) {
//            mVirtualizerStrength = mVirtualizer.getRoundedStrength();//保存当前的值，方便还原
                mVirtualizer.setStrength((short) (preStrength));
                int strength = mVirtualizer.getRoundedStrength();
                Log.d(TAG, "setPlayVirtualizerEffect: strength = " + strength);
            }
        }
    }

    public void setPlayBassBoostEffect(int preStrength) {
        Log.d(TAG, "setPlayBassBoostEffect() called with: preStrenth = [" + preStrength + "]");

        if (mBassBoost != null) {
            mBassBoost.setEnabled(false);
            mBassBoost.release();
            mBassBoost = null;
        }
        if (mMediaPlayer != null) {
            mBassBoost = new BassBoost(0, mMediaPlayer.getAudioSessionId());
            mBassBoost.setEnabled(true);
            if (mBassBoost.getStrengthSupported()) {
                mBassBoost.setStrength((short) (preStrength));
                int strength = mBassBoost.getRoundedStrength();
                Log.d(TAG, "setPlayBassBoostEffect: strength = " + strength);
            }
        }
    }

    private void playAudio(String af) {
        try {
            Log.d(TAG, "playAudio: af = " + af);
            mMediaPlayer.reset();
            mMediaPlayer.setDataSource(af);
            mMediaPlayer.prepare();
//            mMediaPlayer.start();
        } catch (IOException e) {
            e.printStackTrace();
            playStop();

        }
    }

    private void playAudio(File fd) {
        try {
            mMediaPlayer.reset();
            FileInputStream fis = new FileInputStream(fd);
            mMediaPlayer.setDataSource(fis.getFD());
            mMediaPlayer.prepare();
//            mMediaPlayer.start();
        } catch (IOException e) {
            e.printStackTrace();
            playStop();

        }
    }

    private void playAudio(FileInputStream fis) {
        try {
            mMediaPlayer.reset();
            mMediaPlayer.setDataSource(fis.getFD());
            mMediaPlayer.prepare();
//            mMediaPlayer.start();
        } catch (IOException e) {
            e.printStackTrace();
            playStop();
        }
    }


    public void playStop() {
        Log.d(TAG, "playStop: ");
        if (mMediaPlayer == null) {
            return;
        }

        mMediaPlayer.stop();
        mMediaPlayer.release();
        mMediaPlayer = null;
    }

    public boolean isPlaying() {
        if (mAudioTrack != null) {
            int playState = mAudioTrack.getPlayState();
            return playState == AudioTrack.PLAYSTATE_PLAYING;
        }
        return mMediaPlayer != null && mMediaPlayer.isPlaying();
    }

    public void playStart(String src, boolean isPlayLoop) {
        mIsPlayLoop = isPlayLoop;
        playStart(src);
    }

    public interface SamplePlayerStateListener {
        void onStart();

        void onStop();

        void onError(String err);
    }
}
